﻿using System;
using System.Collections.Generic;
using System.Text;
using Stauffware.Common.Core;
using System.Globalization;
using NUnit.Framework;

namespace UnitTests.Core.Parsing
{
	public class NumberLexerTests
	{
		//                   ret   ldg  dgs  sgn   is     dgs   trl         chs 
		//        input	     val   0s   lft  chr   neg    rgt   0s   exp    lxd  error message

		[TestCase(8, NumberParseOptions.None,
					"0",     true, 0,  "0", '\0',  false, "",    0,  null,   1,  null)]
		[TestCase(8, NumberParseOptions.None,
					"1",     true, 0,  "1", '\0',  false, "",    0,  null,   1,  null)]
		[TestCase(8, NumberParseOptions.AllowLeadingSign,
					"-1",    true, 0,  "1",  '-',  true,  "",    0,  null,   2,  null)]
		[TestCase(8, NumberParseOptions.None,
					"987",   true, 0, "987", '\0', false, "",    0,  null,   3,  null)]
		[TestCase(8, NumberParseOptions.AllowLeadingWhite,
					" 1",    true, 0,  "1",  '\0', false, "",    0,  null,   2,  null)]
		[TestCase(8, NumberParseOptions.AllowTrailingWhite | NumberParseOptions.ParseEntireInput,
					"1 ",    true, 0,  "1",  '\0', false, "",    0,  null,   2,  null)]
		[TestCase(8, NumberParseOptions.None,
					"1x",    true, 0,  "1",  '\0', false, "",    0,  null,   1,  null)]
		[TestCase(8, NumberParseOptions.None,
					"1x",    true, 0,  "1",  '\0', false, "",    0,  null,   1,  null)]

		[TestCase(8, NumberParseOptions.AllowDecimalPoint,
					"123.456", true, 0, "123", '\0', false, "456", 0, null, 7, null)]

		[TestCase(8, NumberParseOptions.ParseEntireInput,
					"1x",   false, 0,  "1",  '\0', false, "",    0,  null,   2,  "invalid character in number")]

		[TestCase(8, NumberParseOptions.AllowGrouping,
					"1,234", true, 0, "1234", '\0', false, "", 0, null, 5, null)]
		[TestCase(8, NumberParseOptions.AllowGrouping,
					"12,345", true, 0, "12345", '\0', false, "", 0, null, 6, null)]
		[TestCase(8, NumberParseOptions.AllowGrouping,
					"123,456", true, 0, "123456", '\0', false, "", 0, null, 7, null)]
		[TestCase(8, NumberParseOptions.AllowGrouping,
					"1,234,567", true, 0, "1234567", '\0', false, "", 0, null, 9, null)]


		public static void Test1 (int maxDigits, NumberParseOptions options, string input,
							bool expectedReturnValue,
							int expectedLeadingZeros,
							string expectedDigitsLeft,
							char expectedSignChar,
							bool expectedIsNegative,
							string expectedDigitsRight,
							int expectedTrailingZeros,
							string expectedExponent,
							int expectedCharsLexed,
							string expectedErrorMessage)
		{
			NumberLexer lexer = new NumberLexer(options, null, maxDigits, 3);
			bool retVal = lexer.LexNumber(input);
			bool hasDP = input.Contains('.');

			NUnit.Framework.Assert.AreEqual(expectedReturnValue, retVal, "return value");
			NUnit.Framework.Assert.AreEqual(expectedLeadingZeros, lexer.LeadingZeros, "LeadingZeros");
			NUnit.Framework.Assert.AreEqual(expectedDigitsLeft, lexer.DigitsLeft, "DigitsLeft");
			NUnit.Framework.Assert.AreEqual(expectedSignChar, lexer.SignChar, "SignChar");
			NUnit.Framework.Assert.AreEqual(expectedIsNegative, lexer.IsNegative, "IsNegative");
			NUnit.Framework.Assert.AreEqual(expectedDigitsRight, lexer.DigitsRight, "DigitsRight");
			NUnit.Framework.Assert.AreEqual(expectedTrailingZeros, lexer.TrailingZeros, "TrailingZeros");
			NUnit.Framework.Assert.AreEqual(expectedExponent, lexer.ExponentDigits, "Exponent");
			NUnit.Framework.Assert.AreEqual(hasDP, lexer.HasDecimalPoint, "HasDecimalPoint");
			NUnit.Framework.Assert.AreEqual(expectedCharsLexed, lexer.CharsLexed, "CharsLexed");
			NUnit.Framework.Assert.AreEqual(expectedErrorMessage, lexer.ErrorMessage, "ErrorMessage");
		}

	}

#if false	// old implementation
	[TestFixture(8, NumberParseOptions.None)]
	public class NumberLexerTests
	{
		private readonly NumberLexer NumberLexer;

		public NumberLexerTests (int maxDigits, NumberParseOptions options)
		{
			this.NumberLexer = new NumberLexer(options, null, maxDigits);
		}

		//                   ret   ldg  dgs  sgn   is     dgs   trl         chs 
		//        input	     val   0s   lft  chr   neg    rgt   0s   exp    lxd  error message

		[TestCase("1", true, 0, "1", '\0', false, "", 0, null, 1, null)]

		public void Test1 (string input,
							bool expectedReturnValue,
							int expectedLeadingZeros,
							string expectedDigitsLeft,
							char expectedSignChar,
							bool expectedIsNegative,
							string expectedDigitsRight,
							int expectedTrailingZeros,
							string expectedExponent,
							int expectedCharsLexed,
							string expectedErrorMessage)
		{
			bool retVal = this.NumberLexer.LexNumber(input);

			NUnit.Framework.Assert.AreEqual(expectedReturnValue, retVal, "return value");
			NUnit.Framework.Assert.AreEqual(expectedLeadingZeros, this.NumberLexer.LeadingZeros, "LeadingZeros");
			NUnit.Framework.Assert.AreEqual(expectedDigitsLeft, this.NumberLexer.DigitsLeft, "DigitsLeft");
			NUnit.Framework.Assert.AreEqual(expectedSignChar, this.NumberLexer.SignChar, "SignChar");
			NUnit.Framework.Assert.AreEqual(expectedIsNegative, this.NumberLexer.IsNegative, "IsNegative");
			NUnit.Framework.Assert.AreEqual(expectedDigitsRight, this.NumberLexer.DigitsRight, "DigitsRight");
			NUnit.Framework.Assert.AreEqual(expectedTrailingZeros, this.NumberLexer.TrailingZeros, "TrailingZeros");
			NUnit.Framework.Assert.AreEqual(expectedExponent, this.NumberLexer.Exponent, "Exponent");
			NUnit.Framework.Assert.AreEqual(expectedCharsLexed, this.NumberLexer.CharsLexed, "CharsLexed");
			NUnit.Framework.Assert.AreEqual(expectedErrorMessage, this.NumberLexer.ErrorMessage, "ErrorMessage");
		}
	}
#endif
}
